﻿using System;
using System.Collections.Generic;
using UnityEngine;



public class HerimiteNode
{
    public Vector3 point;
    public float time;

    public HerimiteNode(Vector3 v, float t)
    {
        point = v;
        time = t;
    }

    public HerimiteNode(HerimiteNode n)
    {
        point = n.point;
        time = n.time;
    }
}
public static class LineTools
{
    // 3点贝塞尔曲线
    public static Vector3 GetBezierPos(Vector3 start, Vector3 center, Vector3 end, float t)
    {
        Vector3 p0p1 = (1 - t) * start + t * center;
        Vector3 p1p2 = (1 - t) * center + t * end;
        Vector3 result = (1 - t) * p0p1 + t * p1p2;
        return result;
    }
    // 4点贝塞尔曲线
    public static Vector3 GetBezierPos4(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
    {
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;
        float uuu = uu * u;
        float ttt = tt * t;

        Vector3 p = uuu * p0;
        p += 3 * uu * t * p1;
        p += 3 * u * tt * p2;
        p += ttt * p3;

        return p;
    }

    public static Vector3 GetHerimite(float t, List<HerimiteNode> points, int smoothFactor = 2)
    {
        int k;
        //最后一个顶点
        if (t >= points[points.Count - 2].time)
        {
            return points[points.Count - 2].point;
        }
        for (k = 1; k < points.Count - 2; k++)
        {
            if (points[k].time > t)
                break;
        }

        k = k - 1;
        float param = (t - points[k].time) / (points[k + 1].time - points[k].time);
        return GetHermitNode(k, param, points, smoothFactor);
    }
    public static void CloseHerimite(List<HerimiteNode> points)
    {
        points.Insert(0, points[0]);
        points.Add(points[points.Count - 1]);
    }
    public static Vector3 GetHermitNode(int index, float t, List<HerimiteNode> points, float smoothFactor)
    {
        Vector3 v;
        Vector3 P0 = points[index - 1].point;
        Vector3 P1 = points[index].point;
        Vector3 P2 = points[index + 1].point;
        Vector3 P3 = points[index + 2].point;

        //调和函数
        float h1 = 2 * t * t * t - 3 * t * t + 1;
        float h2 = -2 * t * t * t + 3 * t * t;
        float h3 = t * t * t - 2 * t * t + t;
        float h4 = t * t * t - t * t;

        v = h1 * P1 + h2 * P2 + h3 * (P2 - P0) / smoothFactor + h4 * (P3 - P1) / smoothFactor;
        //Debug.Log(index + "  "+ t+"  "+v);
        return v;
    }

    // 知道距离，重力和速度的情况下，得到抛物线的起始矢量 和耗时
    public static Vector3 GetMoveDir(Vector3 start, Vector3 end, float fGavity, float fMoveSpeed, out float t1)
    {
        var moveDir = new Vector3();
        var dis = end - start;

        float g = fGavity;
        float h = dis.y;
        float v1 = fMoveSpeed;
        // 分成两种，起点比终点低，
        dis.y = 0;
        float s1 = dis.magnitude; // 得到水平距离
        t1 = s1 / v1;     // 得到水平移动的时间

        float v = (2 * h + g * t1 * t1) / (2 * t1);
        moveDir = dis / t1;
        moveDir.y = v;
        return moveDir;

    }
    public static Vector3 GetParabola(Vector3 startPoint, Vector3 endPoint, float speed, float gravity, float time)
    {
        Vector3 direction = (endPoint - startPoint).normalized;
        float distance = Vector3.Distance(startPoint, endPoint);
        float duration = distance / speed;
        float maxHeight = gravity * duration * duration / 8;

        Func<float, float> f = x => -4 * maxHeight * x * x + 4 * maxHeight * x;
        var mid = Vector3.Lerp(startPoint, endPoint, time);
        return new Vector3(mid.x, f(time) + Mathf.Lerp(startPoint.y, endPoint.y, time), mid.z);
    }

    /// <summary>
    /// 获取弧线上的点
    /// </summary>
    /// <param name="start"></param>
    /// 弧线的第一个点
    /// <param name="end"></param>
    /// 弧线的第二个点
    /// <param name="origin"></param>
    /// 所在圆的圆心
    /// <param name="step"></param>
    /// 分成多少段
    /// <returns></returns>
    public static List<Vector3> GetLineArc(Vector3 start, Vector3 end, Vector3 origin, int step)
    {
        List<Vector3> arcPoins = new List<Vector3>();

        float rad = (Vector3.Angle(start, end)) / 180 * Mathf.PI;
        float deg = Vector3.Angle(start, end);
        Quaternion q = Quaternion.FromToRotation(start - origin, end - origin);

        Vector3 dir = start - origin;

        for (int i = 0; i < step; i++)
        {
            float prog = (float)i / (step - 1);
            arcPoins.Add(origin + Quaternion.Lerp(Quaternion.identity, q, prog) * dir);
        }

        return arcPoins;
    }

    public static Vector3 GetLineArcPos(Vector3 start, Vector3 end, Vector3 origin, float fDis)
    {
        List<Vector3> arcPoins = new List<Vector3>();

        arcPoins = GetLineArc(start, end, origin, 10);
        return GetPathPoint(arcPoins, fDis);
    }

    //获取指定路径里指定距离的点
    public static Vector3 GetPathPoint(List<Vector3> path, float fDis)
    {
        float fLen = 0;
        for (int i = 0; i < path.Count - 1; i++)
        {
            Vector2 last = path[i];
            Vector2 cur = path[i + 1];
            fLen += Vector2.Distance(last, cur);
            while (fDis < fLen)
            {
                var pos = Vector2.MoveTowards(cur, last, fLen - fDis);
                return pos;
            }
        }
        return path[path.Count - 1];
    }
}
